package com.ybkj.daijia.api.beatpay.utils;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import org.springframework.core.annotation.AnnotationUtils;

public class JsonUtil {

    private static ObjectMapper objectMapper = null;

    static {
        objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(com.ybkj.daijia.constant.DateConstant.DATE_TIME);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false));
        /**
         * 通过该方法对objectMapper对象进行设置，所有序列化的对象都将按改规则进行系列化
         * Include.Include.ALWAYS 默认
         * Include.NON_DEFAULT 属性为默认值不序列化
         * Include.NON_EMPTY 属性为 空（""） 或者为 NULL 都不序列化
         * Include.NON_NULL 属性为NULL 不序列化
         */
        //objectMapper.setSerializationInclusion(Include.NON_NULL);
        //objectMapper.setSerializationInclusion(Include.NON_EMPTY);
    }

    /**
     * 将对象转换成字符串
     *
     * @param object 转换对象
     * @return
     * @throws JsonProcessingException
     */
    public static String stringify(Object object) throws JsonProcessingException {
        return objectMapper.writeValueAsString(object);
    }

    /**
     * 将对象转换成字符串
     *
     * @param object     转换对象
     * @param properties 转换参数
     * @return
     * @throws JsonProcessingException
     */
    public static String stringify(Object object, String... properties)
        throws JsonProcessingException {
        return objectMapper.writer(new SimpleFilterProvider().addFilter(AnnotationUtils
            .getValue(AnnotationUtils.findAnnotation(object.getClass(), JsonFilter.class))
            .toString(), SimpleBeanPropertyFilter.filterOutAllExcept(properties)))
            .writeValueAsString(object);
    }

    /**
     * 将对象通过流的方式转换成JSON字符串输出流
     *
     * @param out    输出流
     * @param object 转换对象
     * @throws JsonGenerationException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static void stringify(OutputStream out, Object object)
        throws JsonGenerationException, JsonMappingException, IOException {
        objectMapper.writeValue(out, object);
    }

    /**
     * 将对象通过流的方式转换成JSON字符串输出流
     *
     * @param out        输出流
     * @param object     转换对象
     * @param properties 转换参数
     * @throws JsonGenerationException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static void stringify(OutputStream out, Object object, String... properties)
        throws JsonGenerationException, JsonMappingException, IOException {
        objectMapper.writer(new SimpleFilterProvider().addFilter(AnnotationUtils
            .getValue(AnnotationUtils.findAnnotation(object.getClass(), JsonFilter.class))
            .toString(), SimpleBeanPropertyFilter.filterOutAllExcept(properties)))
            .writeValue(out, object);
    }

    /**
     * 将JSON字符串转换成Map
     *
     * @param json JSON串
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    public static Map<String, ?> Parse2Map(String json)
        throws JsonParseException, JsonMappingException, IOException {
        return (Map<String, ?>) Parse(json, Object.class);
    }

    /**
     * 将JSON字符串转换成List
     *
     * @param json JSON串
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    public static List<Map<String, ?>> Parse2List(String json)
        throws JsonParseException, JsonMappingException, IOException {
        return (List<Map<String, ?>>) Parse(json, Object.class);
    }

    /**
     * 将JSON字符串转换成指定对象
     *
     * @param json  JSON串
     * @param clazz 指定对象类
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public static <T> T Parse(String json, Class<T> clazz)
        throws JsonParseException, JsonMappingException, IOException {
        if (json == null || json.length() == 0) {
            return null;
        }
        return objectMapper.readValue(json, clazz);
    }

    /**
     * 将列表型JSON数据转换成对象列表
     *
     * @param json            JSON数据串
     * @param collectionClass 接收集合类
     * @param clazz           接收对象类
     * @return 接收对象集合
     * @throws IOException
     * @throws JsonMappingException
     * @throws JsonParseException
     */
    public static <T> List<T> Parse2List(String json, Class<?> collectionClass, Class<T> clazz)
        throws JsonParseException, JsonMappingException, IOException {
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass,
            clazz); // 通过传入的列表类型和Bean类型，获取一个jackson的javaType
        @SuppressWarnings("unchecked")
        List<T> lst = (List<T>) objectMapper.readValue(json, javaType);
        return lst;
    }
}
